package com.learn.jdk.practice.charter2;

import org.junit.Before;
import org.junit.Test;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static java.util.stream.Collectors.*;


/**
 * @author: lipan
 * @date: 2021/4/24 12:25
 */

public class PraTest {

    List<Dish> menu=null;


    @Before
    public void initData(){

       menu= Arrays.asList(
                new Dish("pork", false, 800, Dish.Type.MEAT),
                new Dish("beef", false, 700, Dish.Type.MEAT),
                new Dish("chicken", false, 400, Dish.Type.MEAT),
                new Dish("french fries", true, 530, Dish.Type.OTHER),
                new Dish("rice", true, 350, Dish.Type.OTHER),
                new Dish("season fruit", true, 120, Dish.Type.OTHER),
                new Dish("pizza", true, 550, Dish.Type.OTHER),
                new Dish("prawns", false, 300, Dish.Type.FISH),
                new Dish("salmon", false, 450, Dish.Type.FISH) );
    }

    /**
     * 求总卡路里
     */
    @Test
    public void test1(){
        Optional<Integer> reduce = menu.stream().map(dish -> dish.getCalories()).reduce(Integer::sum);
        Integer reduce1 = menu.stream().map(dish -> dish.getCalories()).reduce(0, Integer::sum);

        //mapToxx  拆箱
        IntStream intStream = menu.stream().mapToInt(dish -> dish.getCalories());


        Optional<Integer> max = menu.stream().map(dish -> dish.getCalories()).max(Comparator.comparingInt(Integer::intValue));
        System.out.println(max.get());

//        intStream.max();

        //boxed 装箱
        Stream<Integer> boxed = intStream.boxed();


        reduce.ifPresent(System.out::println);
    }

    @Test
    public void test() throws Exception{

        System.out.println(Math.sqrt(4) % 2);
    }


    /**
     * 获取1到100之间的构股数
     * @throws Exception
     */
    @Test
    public void test3() throws Exception{
        Stream<int[]> stream = IntStream.rangeClosed(1, 100).boxed().flatMap(
                a -> IntStream.rangeClosed(a, 100).filter(b -> Math.sqrt(a * a + b * b) % 1 == 0 && Math.sqrt(a * a + b * b)<=100 )
                        .mapToObj(b -> new int[]{a, b, (int) Math.sqrt(a * a + b * b)})
        );

        stream.forEach(t-> System.out.println(t[0]+"\t"+t[1]+"\t"+t[2]));

    }

    /**
     * 读取文件 输出不重复的单词
     * @throws Exception
     */
    @Test
    public void test4() throws Exception{
        try(Stream<String> lines= Files.lines(Paths.get("d:\\test.txt")) ) {
            List<String> collect = lines.flatMap(line -> Arrays.stream(line.split(" "))).distinct().collect(Collectors.toList());
            collect.forEach(System.out::println);
        }catch (Exception e){
        e.printStackTrace();
        }
    }

    /**
     * 无限流
     * @throws Exception
     */
    @Test
    public void test5() throws Exception{

//        Stream.iterate(0,n->n+2).limit(100).forEach(System.out::println);

         Stream.iterate(new int[]{1, 1}, t -> new int[]{t[1], t[0]+ t[1]}).limit(10).forEach(t-> System.out.print(t[0]+"\t"));

    }


    /**
     * 使用分号连接菜名
     * @throws Exception
     */
    @Test
    public void test6() throws Exception{
        String collect = menu.stream().map(Dish::getName).collect(Collectors.joining(","));
        System.out.println(collect);
    }


    /**
     * 计算菜的总热量
     * @throws Exception
     */
    @Test
    public void test7() throws Exception{

        //方式一
        int sum = menu.stream().mapToInt(Dish::getCalories).sum();

        //方式二
        int reduce = menu.stream().mapToInt(Dish::getCalories).reduce(0, (a, b) -> a + b);

        //方式三
        Integer collect = menu.stream().collect(Collectors.reducing(0, Dish::getCalories, (a, b) -> a + b));

        System.out.println(sum+"\t"+reduce+"\t"+collect);
    }


    /**
     * 计算最大热量
     * @throws Exception
     */
    @Test
    public void test8() throws Exception{

        //方式一
        OptionalInt max = menu.stream().mapToInt(Dish::getCalories).max();

        max.ifPresent(System.out::println);


        //方式二
        Optional<Dish> dish = menu.stream().max(Comparator.comparing(Dish::getCalories));
        dish.ifPresent(d-> System.out.println(d.getCalories()));


        //方式三
        Integer reduce = menu.stream().map(Dish::getCalories).reduce(0, Integer::max);

        //方式四
        Integer collect = menu.stream().collect(Collectors.reducing(0, Dish::getCalories, Integer::max));


        System.out.println(reduce+"\t"+collect);

    }


    /**
     * 测试分组
     * @throws Exception
     */
    @Test
    public void test9() throws Exception{

        Map<Dish.Type, List<Dish>> collect = menu.stream().collect(groupingBy(Dish::getType));

        System.out.println(collect);

        Map<String, List<Dish>> collect1 = menu.stream().collect(groupingBy(dish -> {
                    int calories = dish.getCalories();
                    if (calories < 400) {
                        return "低热量";
                    } else {
                        return "高热量";
                    }
                }
        ));

        System.out.println(collect1);


        Map<Dish.Type, Map<String, List<Dish>>> collect2 = menu.stream().collect(groupingBy(Dish::getType, groupingBy(dish -> {
            int calories = dish.getCalories();
            if (calories < 400) {
                return "低热量";
            } else {
                return "高热量";
            }
        })));

        System.out.println(collect2);

        Map<Dish.Type, Long> collect3 = menu.stream().collect(groupingBy(Dish::getType, counting()));
        System.out.println(collect3);

    }

}
